//package com.zrj.auth.config;
//
//import cn.hutool.core.codec.Base64;
//import cn.hutool.core.io.IoUtil;
//import cn.hutool.json.JSONUtil;
//import com.zrj.auth.constant.SecurityConstants;
//import com.zrj.auth.pojo.response.ResultCode;
//import com.zrj.auth.pojo.response.Results;
//import lombok.RequiredArgsConstructor;
//import lombok.SneakyThrows;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.core.convert.converter.Converter;
//import org.springframework.core.io.ClassPathResource;
//import org.springframework.core.io.Resource;
//import org.springframework.core.io.buffer.DataBuffer;
//import org.springframework.core.io.buffer.DataBufferUtils;
//import org.springframework.http.HttpHeaders;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.MediaType;
//import org.springframework.http.server.reactive.ServerHttpResponse;
//import org.springframework.security.authentication.AbstractAuthenticationToken;
//import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
//import org.springframework.security.config.web.server.ServerHttpSecurity;
//import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
//import org.springframework.security.oauth2.jwt.Jwt;
//import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
//import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
//import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
//import org.springframework.security.web.server.SecurityWebFilterChain;
//import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
//import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
//import reactor.core.publisher.Mono;
//
//import java.io.InputStream;
//import java.nio.charset.StandardCharsets;
//import java.security.KeyFactory;
//import java.security.interfaces.RSAPublicKey;
//import java.security.spec.X509EncodedKeySpec;
//
///**
// * 资源服务器配置
// * @author zhaorujie
// * @version 1.0
// * @date 2022/3/21 11:05
// */
//@RequiredArgsConstructor
//@Configuration
//@EnableWebFluxSecurity //开启响应式编程注解
//public class ResourceServerConfig {
//
//    private final ResourceServerManager resourceServerManager;
//
//    @Bean
//    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
//        http.oauth2ResourceServer()
//                .jwt().jwtAuthenticationConverter(jwtAuthenticationConverter())
//                //本地获取公钥
//                .publicKey(rsaPublicKey())
//                .and()
//                .authenticationEntryPoint(authenticationEntryPoint())
//                .and()
//                .authorizeExchange()
//                .pathMatchers("oauth/**").permitAll()
//                .anyExchange().access(resourceServerManager)
//                .and()
//                .exceptionHandling()
//                //处理未授权
//                .accessDeniedHandler(accessDeniedHandler())
//                //处理未认证
//                .authenticationEntryPoint(authenticationEntryPoint())
//                .and()
//                .csrf()
//                .disable()
//        ;
//        return http.build();
//    }
//
//    @Bean
//    public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
//        JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
//        jwtGrantedAuthoritiesConverter.setAuthorityPrefix(SecurityConstants.AUTHORITY_PREFIX);
//        jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(SecurityConstants.JWT_AUTHORITIES_KEY);
//
//        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
//        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
//        return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
//    }
//
//    /**
//     * 本地获取JWT验签公钥
//     * @return
//     */
//    @SneakyThrows
//    @Bean
//    public RSAPublicKey rsaPublicKey() {
//        Resource resource = new ClassPathResource("public.key");
//        InputStream is = resource.getInputStream();
//        String publicKeyData = IoUtil.read(is).toString();
//        X509EncodedKeySpec keySpec = new X509EncodedKeySpec((Base64.decode(publicKeyData)));
//
//        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//        return (RSAPublicKey)keyFactory.generatePublic(keySpec);
//    }
//
//    /**
//     * token无效或者已过期的自定义响应
//     * @return
//     */
//    @Bean
//    public ServerAuthenticationEntryPoint authenticationEntryPoint() {
//        return (exchange, ex) -> {
//            return Mono.defer(() -> Mono.just(exchange.getResponse()))
//                    .flatMap(response -> writeErrorInfo(response, ResultCode.TOKEN_INVALID_OR_EXPIRED));
//        };
//    }
//
//    /**
//     * 自定义未授权
//     * @return
//     */
//    @Bean
//    public ServerAccessDeniedHandler accessDeniedHandler() {
//        return (exchange, denied) -> {
//            return Mono.defer(() -> Mono.just(exchange.getResponse()))
//                    .flatMap(response -> writeErrorInfo(response, ResultCode.ACCESS_UNAUTHORIZED));
//        };
//    }
//
//
//    public  Mono<Void> writeErrorInfo(ServerHttpResponse response, ResultCode resultCode) {
//        switch (resultCode) {
//            case ACCESS_UNAUTHORIZED:
//            case TOKEN_INVALID_OR_EXPIRED:
//                response.setStatusCode(HttpStatus.UNAUTHORIZED);
//                break;
//            case TOKEN_ACCESS_FORBIDDEN:
//                response.setStatusCode(HttpStatus.FORBIDDEN);
//                break;
//            default:
//                response.setStatusCode(HttpStatus.BAD_REQUEST);
//                break;
//        }
//        response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
//        response.getHeaders().set("Access-Control-Allow-Origin", "*");
//        response.getHeaders().set("Cache-Control", "no-cache");
//        String body = JSONUtil.toJsonStr(Results.failed(resultCode));
//        DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));
//        return response.writeWith(Mono.just(buffer))
//                .doOnError(error -> DataBufferUtils.release(buffer));
//    }
//}
